package internal

import (
	"context"
	"errors"
	"time"

	"engine/db"
	"engine/log"
	"gitee.com/ameise84/e3utils/str_conv"
	"gitee.com/ameise84/e3utils/uuid"
	"github.com/redis/go-redis/v9"

	"servers/cache"
	"servers/models/db_meta"
	"servers/models/define"
	"servers/models/error_code"
	"servers/models/protos/google/pb/rpc_protos"
	"servers/models/redis_help"
)

func OnCreateAccountReq(msg *rpc_protos.CreateAccountReq) *rpc_protos.CreateAccountRsp {
	dr := db.GetDumper()
	meta := db_meta.AcPlayer{}
	meta.FromPBMeta(msg.Account)
	rsp := &rpc_protos.CreateAccountRsp{}
	if err := dr.Create(&meta).Error; err != nil {
		rsp.Code = error_code.ErrorCodeAccountIsExist
	} else {
		rsp.UserID = meta.UserID
	}
	return rsp
}

func OnLoginGetTokenReq(msg *rpc_protos.LoginGetTokenReq) *rpc_protos.LoginGetTokenRsp {
	rsp := &rpc_protos.LoginGetTokenRsp{}
	if msg.IsGuest {
		log.GetLogger().Error("guest get token not defined").Println()
		rsp.Code = error_code.ErrorCodeUnknown
	} else {
		dbCli := db.GetInstance()
		redisCli := db.GetRedis()

		accountMeta := db_meta.AcPlayer{}
		if err := dbCli.HGet(&accountMeta, str_conv.ToString(msg.UserID)); err != nil {
			if errors.Is(err, redis.Nil) {
				rsp.Code = error_code.ErrorCodeAccountIsNotExist
			} else {
				log.GetLogger().ErrorPrintf("on login get token err:%v", err)
				rsp.Code = error_code.ErrorCodeServiceBusy
			}
			return rsp
		}

		token := uuid.NewShortV4()
		r, err := redisCli.Pipelined(context.Background(), func(pip redis.Pipeliner) error {
			k1 := redis_help.KeyTokenToUserID(token)
			k2 := redis_help.KeyUserIDToToken(msg.UserID)
			ttl := time.Now().Add(define.RedisTokenTTL)
			pip.Set(context.Background(), k1, redis_help.Join(accountMeta.BusinessID, msg.UserID), define.RedisTokenTTL)
			pip.GetSet(context.Background(), k2, token)
			pip.ExpireAt(context.Background(), k2, ttl)
			return nil
		})

		if err != nil && !errors.Is(err, redis.Nil) {
			log.GetLogger().ErrorPrintf("on login get token err:%v", err)
			rsp.Code = error_code.ErrorCodeServiceBusy
		} else {
			rs, _ := r[1].(*redis.StringCmd).Result()
			if rs != "" {
				redisCli.Del(context.Background(), redis_help.KeyTokenToUserID(rs))
			}
			rsp.Token = token
		}
	}
	return rsp
}

func OnGetGameListReq(msg *rpc_protos.GetGameListReq) *rpc_protos.GetGameListRsp {
	rsp := &rpc_protos.GetGameListRsp{
		GameList: make([]*rpc_protos.GameBaseInfoMeta, 0, 128),
	}
	business, ok := cache.GetBusinessInfo(msg.BusinessID)
	if !ok {
		rsp.Code = error_code.ErrorCodeBusinessIsNotExist
		return rsp
	}
	group, ok := cache.GetGameGroup(business.GameGroupID)
	if !ok {
		rsp.Code = error_code.ErrorCodeServiceBusy
		return rsp
	}
	for _, meta := range group.List {
		i18n := cache.GetI18N(msg.Lang, meta.Name, meta.Image)
		rsp.GameList = append(rsp.GameList, &rpc_protos.GameBaseInfoMeta{
			GameKindID: meta.GameKindID,
			GameType:   meta.GameType,
			Name:       i18n[0],
			Image:      i18n[1],
			Sort:       meta.Sort,
			Mark:       meta.Mark,
		})
	}
	return rsp
}
